On TUIs

published on 2023-08-19 by dzwdz

I’m using a relatively modern terminal emulator. It has snappy native scrolling, with e.g. great touchpad support. I can search the scrollback with a single hotkey. The way I navigate and use it is consistent across all cli utilities. That is, except TUIs.

scrollback

Most TUI programs—IRC clients, (web/gopher/gemini) browsers, mail clients—use custom scroll widgets, as opposed to just printing all the data and letting the terminal handle scrolling.

If you’re using them over ssh, scrolling turns from something your terminal can do instantly, to something that requires a roundtrip for each unit scrolled. This makes them painful to use on high latency connections, which would otherwise have enough bandwidth to just transfer all scrolled text. It also breaks touch support, as you lose pixel-wise scrolling, and the lag makes it harder to predict the length of a scroll.

Every program has its own bespoke set of hotkeys, so you lose out on consistency. Some programs have vi bindings, some don’t. Some don’t even support arrow keys. Search support will differ, too, with a slightly different implementation in each program that supports it.

You already pretty much need scrollback and search for regular shell usage, though. Even if you’re using a “dumb” terminal, you’re probably using something like tmux to provide that. Why, then, should programs reimplement what’s already provided for you by the terminal?

One common reason is top/sidebars. The terminal protocol we use is too primitive to express multiple windows, so scrolling a program with a sidebar ends up looking wrong. It’s a tradeoff, sure, but IMO the benefits of using the terminal’s scrollback outweight the benefits of sidebars. In most cases, you don’t really need them:

I’m not saying top/sidebars are useless. They’re great in true GUIs, where using a sidebar doesn’t mean you’re no longer allowed to use native widgets. Sadly, terminals are much dumber than that. If you want to use them well, blindly copying GUI conventions isn’t the way to go.

improving the situation

The tradeoff would mostly be gone if terminals were extended to allow GUI-like subwindows. I believe that was one of notty’s goals. rio sort of supports that, too.

line editing

Speaking of rio, it had some good ideas. One of them was the “output point”. It separated the program output from your current input. Instead of directly sending your input to the program, it let rio function as a line editor.

It had autocompletion, utf8 support, and gracefully handled program output during editing. If the program sent some text, your input was moved out of the way. If the program erased some text (\b), your input was moved back to the available space.

Going back to the status quo—this is actually pretty hard to achieve, if you’re not also reimplementing a scroll widget. If you want to input and output text at the same time (think netcat, or an IRC client), your two options are:

Similarly, just as with custom scroll widgets, line editing over a high latency connection hurts, because you need to do a full roundtrip for each character typed.

Also, some utf8 characters have ambiguous width. Only the terminal knows how they will be rendered, so, if you want your line editor to be fully correct, you’d have to poll the position after each such character printed.

Doesn’t this suggest that line editing would be better handled on the terminal’s end, as in rio?

appendix: autocompletion

How would autocompletion work if line editing was implemented in the terminal? rio was limited to autocompleting paths, but here’s my idea for a more general approach:

When a program with support for autocomplete starts, it’d send an escape code to notify the terminal that it can use autocomplete. Similarly, it’d disable autocomplete support when launching another program, or quitting.

On <Tab>, the terminal would send the current, incomplete, line wrapped in another set of escape codes. The program would recognize that, and respond with a list of possible completions, potentially also informing the terminal that it can request more.

tldr

  1. Scrolling through TUI sucks.
  2. I wish terminals handled line editing.